#include "Obstacle.h"
#include "CSurface.h"
#include "CApp.h"
#include "Vectores.h"
#include <iostream>

#include <SDL/SDL.h>

using namespace std;

Obstacle::Obstacle(int x, int y, int z, int w, int h){
  position[0] = x;
  position[1] = y;
  position[2] = z;
  this->w = w;
  this->h = h;
  surface = CSurface::OnLoad("images/obstaculoArbustos.bmp");
  CSurface::Transparent(surface, 0, 183, 239);
}

void Obstacle::OnRender(SDL_Surface* display){
    CSurface::OnDraw(display,
            surface,
            fixX(position[0]), fixY(position[1]-20));
}

bool Obstacle::collideWith(Character* charac,
    float **current, float **I, float **N){
  int i;
  int d[4], min;
  float tg, a, b, c;
  float *p = NULL;
  Kinematic* kine = charac->getKinematic();
  Kinematic* kine2;
  float *vel = kine->velocity;
  float S[3];
  float diff[][3] = {
    {0,0,0},
    {0, -charac->getHeight()/3,0},
    {charac->getWidth()/3,0,0},
    {0, charac->getHeight()/3,0},
    {-charac->getWidth()/3,0,0}
  };
  int j;
  bool resp = false;

  for(j=0; j<5; j++){
    kine2 = charac->getKinematic();
    p = kine2->position;
    p[0] += diff[j][0];
    p[1] += diff[j][1];
    p[2] += diff[j][2];

//  printf(" |%03.2f == %03.2f|  |%03.2f == %03.2f|  (%03.2f  %03.2f) %d, %d\n",
//      position[0], position[0]+w,
//      position[1], position[1]+h,
//      p[0], p[1],
//      position[0]<p[0] && p[0]<position[0]+w,
//      position[1]<p[1] && p[1]<position[1]+h
//      );

    // Verificamos si choco con el obstaculo
    if(
        position[0]<p[0] && p[0]<position[0]+w
        && position[1]<p[1] && p[1]<position[1]+h
        && p[2]<600
      ){

      // Verificamos por que lado chocamos
      d[0] = p[1] - position[1];
      d[1] = position[0]+w - p[0];
      d[2] = position[1]+h - p[1];
      d[3] = p[0] - position[0];

      for(i=1, min=0; i<4; i++){
        if(d[i]<d[min]) min=i;
      }

      tg = vel[1]/vel[0];
      a = tg;
      b = -tg*p[0] + p[1];

      if(min==0 || min==2){
        // choco con una pared vertical
        if(min==0){
          c=position[1];
          (*N)[0] = 0;
          (*N)[1] = -1;
        } else {
          c = position[1]+h;
          (*N)[0] = 0;
          (*N)[1] = 1;
        }

        // Punto de colicion
        (*I)[0] = (c-b)/a;
        (*I)[1] = c;

        S[0] = p[0]-(*I)[0];
        S[1] = p[1]-(*I)[1];

        // Donde deberia estar el character
        (*current)[0] = p[0] - diff[j][0];
        (*current)[1] = p[1] - 2*S[1] - diff[j][1];

      } else {
        // choco con una pared horizontal
        if(min==1){
          c=position[0]+w;
          (*N)[0] = 1;
          (*N)[1] = 0;
        } else {
          c = position[0];
          (*N)[0] = -1;
          (*N)[1] = 0;
        }

        // Punto de colicion
        (*I)[0] = c;
        (*I)[1] = a*c + b;

        S[0] = p[0]-(*I)[0];
        S[1] = p[1]-(*I)[1];

        // Donde deberia estar el character
        (*current)[0] = p[0] - 2*S[0] - diff[j][0];
        (*current)[1] = p[1] - diff[j][1];
      }

      resp = true;
      break;
    }

    delete kine2;
  }
  delete kine;

  return resp;
}

bool Obstacle::collideWith(float p[3], float vel[3],
    float **current, float **I, float **N){
  int i;
  int d[4], min;
  float tg, a, b, c;
  float S[3];
  bool resp = false;

//  printf(" |%03.2f == %03.2f|  |%03.2f == %03.2f|  (%03.2f  %03.2f) %d, %d\n",
//      position[0], position[0]+w,
//      position[1], position[1]+h,
//      p[0], p[1],
//      position[0]<p[0] && p[0]<position[0]+w,
//      position[1]<p[1] && p[1]<position[1]+h
//      );

  // Verificamos si choco con el obstaculo
  if(
      position[0]<p[0] && p[0]<position[0]+w
      && position[1]<p[1] && p[1]<position[1]+h
      && p[2]<600
    ){

    // Verificamos por que lado chocamos
    d[0] = p[1] - position[1];
    d[1] = position[0]+w - p[0];
    d[2] = position[1]+h - p[1];
    d[3] = p[0] - position[0];

    for(i=1, min=0; i<4; i++){
      if(d[i]<d[min]) min=i;
    }

    tg = vel[1]/vel[0];
    a = tg;
    b = -tg*p[0] + p[1];

    if(min==0 || min==2){
      // choco con una pared vertical
      if(min==0){
        c=position[1];
        (*N)[0] = 0;
        (*N)[1] = -1;
      } else {
        c = position[1]+h;
        (*N)[0] = 0;
        (*N)[1] = 1;
      }

      // Punto de colicion
      (*I)[0] = (c-b)/a;
      (*I)[1] = c;

      S[0] = p[0]-(*I)[0];
      S[1] = p[1]-(*I)[1];

      // Donde deberia estar el character
      (*current)[0] = p[0];
      (*current)[1] = p[1] - 2*S[1];

    } else {
      // choco con una pared horizontal
      if(min==1){
        c=position[0]+w;
        (*N)[0] = 1;
        (*N)[1] = 0;
      } else {
        c = position[0];
        (*N)[0] = -1;
        (*N)[1] = 0;
      }

      // Punto de colicion
      (*I)[0] = c;
      (*I)[1] = a*c + b;

      S[0] = p[0]-(*I)[0];
      S[1] = p[1]-(*I)[1];

      // Donde deberia estar el character
      (*current)[0] = p[0] - 2*S[0];
      (*current)[1] = p[1];
    }

    resp = true;
  }

  return resp;
}

ObstacleMuro::ObstacleMuro(int x, int y, int z, int w, int h):
        Obstacle(x,y,z,w,h){
    position[0] = x;
    position[1] = y;
    position[2] = z;

    this->w = w;
    this->h = h;

    surface = CSurface::OnLoad("images/obstaculo.bmp");
    CSurface::Transparent(surface, 0, 183, 239);
}

void ObstacleMuro::OnRender(SDL_Surface* display){
    CSurface::OnDraw(display,
            surface,
            fixX(position[0]), fixY(position[1]-20));
}

ObstacleVolcan::ObstacleVolcan(int x, int y, int z, int w, int h):
        Obstacle(x,y,z,w,h){
    a = new AnimationVolcan();
    position[0] = x;
    position[1] = y;
    position[2] = z;
    this->w = w;
    this->h = h;
    surface = CSurface::OnLoad("images/volcan.bmp");
    CSurface::Transparent(surface, 0, 183, 239);
    old_time = SDL_GetTicks();
    off = false;
}

void ObstacleVolcan::OnRender(SDL_Surface* display){
    Uint32 current_time = SDL_GetTicks();
    if (!off && current_time -old_time > 8000){
      off = true;
      old_time = current_time;
      a->finishAnimation();
    }else{
      a->OnAnimate();
    }
    if (off && current_time - old_time > 3000){
      a->startAnimation();
      off = false;
      old_time =  current_time;
    }
    CSurface::OnDraw(display,
            a->getFrame(),
            fixX(position[0]), fixY(position[1]),
            a->getX(),a->getY(),a->getWidth(),a->getHeight()
            );
}
